#pragma once

#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<netinet/in.h>
#include<cstring>
#include<arpa/inet.h>
#include<fcntl.h>
#include<signal.h>


#define BACK_LOG 5

using namespace std;
//服务器端 需要关注ip地址，port给定即可
class TcpSever
{
  private:
    int port;//三次握手  监听 接受
    int lsock;
  public:
    TcpSever(int _port) : port(_port)  ,lsock(-1)
    {}
    bool init_tcp_sever()
    {
      lsock=socket(AF_INET,SOCK_STREAM,0);
      //判断是否创建成功
      if(lsock<0)
      {
        cerr<<"creat sock fail"<<endl;
        return false;
      }
      //ip和端口绑定，表示网络中唯一的进程
      struct sockaddr_in local;
      memset(&local,0,sizeof(local));
      local.sin_family=AF_INET;
      local.sin_port=htons(port);
      local.sin_addr.s_addr=INADDR_ANY;//接受任意ip传信息，设置传入数据的ip


      if(bind(lsock,(struct sockaddr*)&local,sizeof(local))<0)
      {
        //绑定失败
        cout<<"bind fail "<<endl;
        return false;
      }
      //绑定成功，监听连接的ip
      if(listen(lsock,BACK_LOG)<0)
      {
        cout<<" listen fail "<<endl;
        return false;
      }
      //绑定成功  监听成功  有ip连接到服务端
      return true;
    }
    void Loop()
    {
      signal(SIGCHLD,SIG_IGN);
      struct sockaddr_in peer;
      for(;;)
      {
        socklen_t len=sizeof(peer);
        //接受套接字，服务
        int sock=accept(lsock,(struct sockaddr*)&peer,&len);
        if(sock<0)
        {
          cout<<"accept fail continue next"<<endl;
          continue;
        }
        //接受成功，对客户端进行服务，使用多进程服务
        //让孙子进程服务，被系统领养
        pid_t id=fork();
        if(id==0)
        {
          //爸爸进程
          close(lsock);
          if(fork()>0)
          {
            //爸爸进程退出
            exit(0);
          }
          //孙子进程服务
          string ip=inet_ntoa(peer.sin_addr);//需要从网络整形变成网址的样子
          int port=ntohs(peer.sin_port);
          cout << "get a new link->"<< sock << " [" << ip << "]:" << port << endl;
          sevice(sock,ip,port);
          exit(0);
        }
        close(sock);
        waitpid(id,nullptr,0);
      }
    }
    void sevice(int sock,string ip,int port)
    {
        char buffer[1024];
        while(1)
        {
          //读取数据
          ssize_t size=read(sock,buffer,sizeof(buffer)-1);
          if(size>0)
          {
            buffer[size]=0;
            cout<<ip<<":"<<port<<":"<<" #  "<<buffer<<endl;
            //让客户端也收到信息
            write(sock,buffer,size);
          }
          else if(size==0)
          {
            //没数据了，对端关闭
            cout<<ip<<":"<<port<<":"<<"close"<<endl;
            break;
          }
          else
          {
            cout<<sock<<"read fail"<<endl;
            break;
          }
        }
        cout<<"sevice done "<<endl;
    }
    ~TcpSever()
    {
      if(lsock>=0)
      {
        close(lsock);
      }
    }
};
